-- 遗迹探宝 战斗相关

local Msg = require("core.Msg")
local CombatDefine = require("combat.CombatDefine")
local YjTreasureDBLogic = require("yjTreasure.YjTreasureDB")
local YjTreasureLogic = require("yjTreasure.YjTreasureLogic")
local CombatImpl = require("combat.CombatImpl")
local BagLogic = require("bag.BagLogic")
local CombatLogic = require("combat.CombatLogic")
local YjTreasureExcel = require("excel.yjTreasure")
local LiLianLogic = require("dailyTask.LiLianLogic")
local CombatObj = require("combat.CombatObj")
local Broadcast = require("broadcast.Broadcast")
local Lang = require("common.Lang")
local Util = require("common.Util")
local RoleDefine = require("role.RoleDefine")
local MonsterExcel = require("excel.monster")
local ChengjiuLogic = require("chengjiu.ChengjiuLogic")
local ChengjiuDefine = require("chengjiu.ChengjiuDefine")
local RoleSystemLogic = require("roleSystem.RoleSystemLogic")
local RoleSystemDefine = require("roleSystem.RoleSystemDefine")
local Grid = require("bag.Grid")
local HeroGrowUp = require("absAct.HeroGrowUp")
local MengxinLogic = require("present.MengxinLogic")
local Log = require("common.Log")
local CommonDB = require("common.CommonDB")

--能否上阵
function checkUpdatePos(human)
	if not YjTreasureLogic.isOpen(human,true) then return end

	local roleData = YjTreasureDBLogic.getRoleDataByUuid(human.db._id)
	if roleData and roleData.objList then return end

	return true
end

--保存上阵
function onUpdatePos(human)
	if not YjTreasureLogic.isOpen(human,true) then return end
	if not checkUpdatePos(human) then return end
	local objList, _, rolebase = CombatLogic.getHumanObjList(human, CombatDefine.COMBAT_TYPE10)
	if not objList or not rolebase then return end

    local yjTime = CommonDB.getYjTreasureEndTime()
	if not yjTime then
		YjTreasureDBLogic.initDB() --活动db初始化
	end

	local roleData = YjTreasureDBLogic.getRoleDataByUuid(human.db._id)
	if not roleData then
		YjTreasureDBLogic.addPlayer(objList,rolebase,human.db._id) --活动db增加玩家信息
	else
        YjTreasureDBLogic.YJ_Rank2Uuid[#YjTreasureDBLogic.YJ_Rank2Uuid + 1] = human.db._id
		roleData.time = os.time()
		roleData.objList = Util.copyTable(objList)
		roleData.rolebase = Util.copyTable(rolebase)
		local creatLayer = 1
		if roleData.layerMax then
			creatLayer = roleData.layerMax - YjTreasureExcel.define[1].backLayer
			if creatLayer <= 0 then
				creatLayer = 1
			end
		end
		YjTreasureDBLogic.creatLayerData(roleData,creatLayer)
		YjTreasureDBLogic.setFightHero(roleData.objList)
		YjTreasureDBLogic.updateUuid2Role(roleData)
		YjTreasureDBLogic.sortYJboard()
	end
	YjTreasureLogic.CG_YJTREASURE_QUERY(human)
    RoleSystemLogic.onDot(human, RoleSystemDefine.ROLE_SYS_ID_1207)
    RoleSystemLogic.onDot(human, RoleSystemDefine.ROLE_SYS_ID_1202)
end

--战斗 选择出战
function CG_YJTREASURE_UPDATE_FIGHT(human,pos)
	if not YjTreasureLogic.isOpen(human, true) then return end
	local roleData = YjTreasureDBLogic.getRoleDataByUuid(human.db._id)
	if not roleData or not roleData.objList then return end
	if not YjTreasureDBLogic.setFightHero(roleData.objList,pos) then return Broadcast.sendErr(human, Lang.YJTREASURE_YAOJI_CURE_ERR2) end
	YjTreasureDBLogic.updateUuid2Role(roleData)

	local msgRet = Msg.gc.GC_YJTREASURE_UPDATE_FIGHT
	msgRet.pos = pos
	--Msg.trace(msgRet)
	Msg.send(msgRet,human.fd)
end

local function getMonsterFormation(human,gridIndex)
	local defCnf = YjTreasureExcel.define[1]
	local layerData = YjTreasureDBLogic.getLayerDataByUuid(human.db._id)
	local monstersData = YjTreasureExcel.layer[layerData.layer].monsters
	local bossData = YjTreasureExcel.layer[layerData.layer].boss

	local monsterOutID = nil
	if gridIndex == defCnf.bossGrid then
		monsterOutID = bossData
	else
		local monstersGrid = defCnf.monstersGrid
		for i=1,#monstersGrid do
			if monstersGrid[i] == gridIndex then
				monsterOutID = monstersData[i]
			end
		end
	end

	if not monsterOutID then return 1 end

	return MonsterExcel.monsterOut[monsterOutID].formation
end

-- 获取出战对象列表
function getCombatObjList(human, side, gridIndex)
	if not YjTreasureLogic.isOpen(human, true) then return end
	local roleData = YjTreasureDBLogic.getRoleDataByUuid(human.db._id)
	if side == CombatDefine.ATTACK_SIDE then
		if not roleData.objList then
			return 
		end
		local obj, pos = YjTreasureDBLogic.getFightHeroObj(roleData.objList)
		if not obj then return end
		local heroList = {[pos] = obj}
		local rolebase = CombatLogic.createRoleBaseByDB(human.db, obj.attrs[RoleDefine.ZHANDOULI])
		return heroList, nil, rolebase, 5
	elseif side == CombatDefine.DEFEND_SIDE then
		local gridData = YjTreasureDBLogic.getGridDataByIndex(human.db._id,gridIndex)
		if not gridData.monsterObjList then return end
		local monsterList = {}
		for pos, monsterObj in pairs(gridData.monsterObjList) do
			if YjTreasureDBLogic.getCombatObjHp(monsterObj) > 0 then
				monsterList[pos] = monsterObj
			end
		end

		local formation = getMonsterFormation(human,gridIndex)

		return monsterList, nil, gridData.monsterRBase, formation
	end
end

function fight(human,args)
	if not YjTreasureLogic.isOpen(human,true) then return end
	local gridIndex = tonumber(args[1])
	local gridsData = YjTreasureDBLogic.getGridsData(human.db._id)
	if not gridsData or not gridsData[gridIndex] then return end

	local gridData = gridsData[gridIndex]

	local defCnf = YjTreasureExcel.define[1]
	local bossGrid = defCnf.bossGrid
	if gridIndex == bossGrid then
		if gridData.gridType ~= YjTreasureLogic.YJ_TREASURE_GRID_BOSS then
			return
		end

		if not gridData.isOpen then
			return Broadcast.sendErr(human,Lang.YJTREASURE_BOSS_NOT_OPEN)
		end
	else
		if gridData.gridType ~= YjTreasureLogic.YJ_TREASURE_GRID_MONSTER then
			return
		end
	end

	local objList = YjTreasureDBLogic.getObjList(human.db._id)
	if not objList then return end

	if not YjTreasureDBLogic.getFightHeroObj(objList) then
		return Broadcast.sendErr(human, Lang.YJTREASURE_COMBAT_ERR_ALLDIE)
	end

    local layerData = YjTreasureDBLogic.getLayerDataByUuid(human.db._id)
	local layerConfig = YjTreasureExcel.layer[layerData.layer]
    if not layerConfig then return end

	local isQuick = human.db.combatQuick[CombatDefine.COMBAT_TYPE10]
	CombatLogic.combatBegin(human, layerConfig.mapID, gridIndex, CombatDefine.COMBAT_TYPE10, gridIndex, isQuick == 1)
end


-- 获取当前地图ID
function getMapID(human, args)
    local layerData = YjTreasureDBLogic.getLayerDataByUuid(human.db._id)
	local layerConfig = YjTreasureExcel.layer[layerData.layer]
    if not layerConfig then return end
    return layerConfig.mapID
end

-- 附加属性
local function addAttrs(obj, attrs)
	if not attrs then return end

	obj.isSysAttrChange = true
	for key, value in pairs(attrs) do
		obj.sysAttr[key] = obj.sysAttr[key] + value	
	end	
end

-- 战前添加属性
function onFightBegin(human, param, combatType)
	if not YjTreasureLogic.isOpen(human) then return end
    local gridIndex = param.cbParam
    local changePos = param.changePos
	local buffData = YjTreasureDBLogic.getBuffData(human.db._id)
	local objList = YjTreasureDBLogic.getObjList(human.db._id)
	local gridData = YjTreasureDBLogic.getGridDataByIndex(human.db._id,gridIndex)
	--require("common.Util").printTable(gridData)

	local attrs = nil
	if buffData then
		for key, value in pairs(buffData) do
			attrs = attrs or {}
			attrs[key] = (attrs[key] or 0) + value
		end
	end
	for i = 1, CombatDefine.COMBAT_HERO_ALL_CNT do
		local data = CombatImpl.objList[i]
		if data then
            local pos = i
            if i <= 10 then
                pos = changePos
            end
			local index = CombatLogic.getIndexByPos(data.side, pos)
			local obj = nil
			if data.side == CombatDefine.ATTACK_SIDE then
				addAttrs(data, attrs)
				obj = objList[index]
			else
				obj = gridData.monsterObjList[index]
			end
			if obj and obj.hp then
				data.hp = obj.hp
			end
		end
	end	
end

-- 刷新剩余血量
function resetCombatHp(uuid,combatInfo,gridIndex)
	local isDie = nil
	local gridsData = YjTreasureDBLogic.getGridsData(uuid,gridIndex)
    local gridData = gridsData[gridIndex]
	local roleData = YjTreasureDBLogic.getRoleDataByUuid(uuid)
	local objList = roleData.objList

	for i = 1, CombatDefine.COMBAT_HERO_ALL_CNT do
		local data = combatInfo.objList[i]
		if data then
            if data.side == CombatDefine.ATTACK_SIDE and combatInfo.changePos then
                data.pos = combatInfo.changePos
            end
			local index = CombatLogic.getIndexByPos(data.side, data.pos)
			local obj = nil
			if data.side == CombatDefine.ATTACK_SIDE then
				obj = objList[index]
				if data.hp <= 0 then isDie = true end
			else
				obj = gridData.monsterObjList[index]
			end
			obj.hp = data.hp
			obj.hpMax = CombatObj.getHpMax(data)			
		end
	end	
	if isDie then
		YjTreasureDBLogic.setFightHero(objList)
	end
	roleData.layerData.grids = gridsData
	YjTreasureDBLogic.updateUuid2Role(roleData)
end

local function getkillOpenGrids(gridIndex)
	local defCnf = YjTreasureExcel.define[1]
	local openCnfIndex = nil
	for i=1,#defCnf.monstersGrid do
		if defCnf.monstersGrid[i] == gridIndex then
			openCnfIndex = i
		end
	end
	if not openCnfIndex then return end
	return defCnf.killOpenGrids[openCnfIndex],openCnfIndex
end

local function isKill(uuid,needkillIndex)
	local defCnf = YjTreasureExcel.define[1]
	local needKillGridIndex = defCnf.monstersGrid[needkillIndex]
	--print("needkillIndex,needKillGridIndex",needkillIndex,needKillGridIndex)
	if not needKillGridIndex then return end
	local gridData = YjTreasureDBLogic.getGridDataByIndex(uuid,needKillGridIndex)
	if not gridData then return end
	--print("gridData.gridType",gridData.gridType)
	if gridData.gridType == YjTreasureLogic.YJ_TREASURE_GRID_KONGDI then
		return true
	end
end

function getOpenGrids(uuid,gridIndex)
	local defCnf = YjTreasureExcel.define[1]

	local killOpenGrids,openCnfIndex = getkillOpenGrids(gridIndex)
	if not killOpenGrids then return end

	local chongdieOpen = {}
	local chongDieGridsCnf = defCnf.chongDieGrids[openCnfIndex]
	for i=1,#chongDieGridsCnf do
		local needKill = chongDieGridsCnf[i][1]
		local isKill = isKill(uuid,needKill)
		--print("needKill,isKill",needKill,isKill)
		for j=2,#chongDieGridsCnf[i] do
			local chongdie = chongDieGridsCnf[i][j]
			chongdieOpen[chongdie] = {}
			chongdieOpen[chongdie].canOpen = nil
			if isKill then
				chongdieOpen[chongdie].canOpen = true
			end
		end
	end

	local openGrids = {}
	for i=1,#killOpenGrids do
		local gridIndex = killOpenGrids[i]
		if chongdieOpen[gridIndex] then 
			if chongdieOpen[gridIndex].canOpen then
				openGrids[#openGrids + 1] = gridIndex
			end
		else
			openGrids[#openGrids + 1] = gridIndex
		end
	end

	return openGrids
end

-- 战斗结束
function killMonsterOpenGrids(human,gridIndex)
	local defCnf = YjTreasureExcel.define[1]
	local roleData = YjTreasureDBLogic.getRoleDataByUuid(human.db._id)
	local layerData = roleData.layerData
	if not layerData then return end
	local gridsData = layerData.grids
	if not gridsData then return end
	local gridData = gridsData[gridIndex]
	if not gridData then return end

    local buff = nil
    local itemTb = {}
	local msgRet = Msg.gc.GC_YJTREASURE_OPENGRIDS
	msgRet.list[0] = 0
	if gridData.gridType == YjTreasureLogic.YJ_TREASURE_GRID_BOSS then
		gridsData[gridIndex] = {}
		gridsData[gridIndex].gridType = YjTreasureLogic.YJ_TREASURE_GRID_DOOR
		gridsData[gridIndex].isOpen = 1
		roleData.tansuo = (roleData.tansuo or 0) + 1
	elseif gridData.gridType == YjTreasureLogic.YJ_TREASURE_GRID_MONSTER then
		local openGrids = getOpenGrids(human.db._id,gridIndex)
		if not openGrids then return end

		gridsData[gridIndex] = {}
		gridsData[gridIndex].gridType = YjTreasureLogic.YJ_TREASURE_GRID_KONGDI
		gridsData[gridIndex].isOpen = 1

		roleData.tansuo = (roleData.tansuo or 0) + #openGrids + 1 --算上怪物格子
		--BagLogic.cleanMomentItemList()
		for i=1,#openGrids do
			local openIndex = openGrids[i]
			local data = gridsData[openIndex]
			local change = nil

			if data.gridType == YjTreasureLogic.YJ_TREASURE_GRID_ITEM then --道具
				local item = data.item
				if item then
					local itemID = item.itemID
					local itemCnt = item.itemCnt
					--BagLogic.updateMomentItem(2, itemID, itemCnt)
					layerData.getItems = layerData.getItems or {}
					layerData.getItems[itemID] = (layerData.getItems[itemID] or 0) + itemCnt
                    itemTb[itemID] = (itemTb[itemID] or 0 ) + itemCnt
				end
				change = true
			end

			if data.gridType == YjTreasureLogic.YJ_TREASURE_GRID_YJSHOPER then --遗迹商人
				roleData.yjShoperCnt = (roleData.yjShoperCnt or 0) + 1
				change = true
			end

			if data.gridType == YjTreasureLogic.YJ_TREASURE_GRID_TREASURE_SHOP then --商店
				YjTreasureDBLogic.makeTreasureShop(human.db._id,openIndex)
			end

			if data.gridType == YjTreasureLogic.YJ_TREASURE_GRID_BUFF then --buff
				change = true
				buff = YjTreasureDBLogic.makeBuff(human.db._id)
                local msg = Msg.gc.GC_YJTREASURE_BUFF_GET
                msg.buff.key = buff[1]
                msg.buff.value = buff[2]
                Msg.send(msg,human.fd)
			end

			gridsData[openIndex].isOpen = 1

			if change then
				msgRet.list[0] = msgRet.list[0] + 1
				local index = msgRet.list[0]
				YjTreasureLogic.makeYjGridNet(human,msgRet.list[index],openIndex,data)

				gridsData[openIndex] = {}
				gridsData[openIndex].gridType = YjTreasureLogic.YJ_TREASURE_GRID_KONGDI
				gridsData[openIndex].isOpen = 1
			end
		end
		--BagLogic.addMomentItemList(human, "yj_treasure")
        local msg = Msg.gc.GC_YJTREASURE_GET_ITEM
        local msgLen = 0
        for itemID,itemCnt in pairs(itemTb) do
            BagLogic.addItem(human,itemID,itemCnt,"yj_treasure")
            msgLen = msgLen + 1
            Grid.makeItem(msg.item[msgLen],itemID,itemCnt)
        end
        msg.item[0] = msgLen
        Msg.send(msg,human.fd)
        --BagLogic.cleanMomentItemList()
		--四个守卫击败，方可挑战boss
		if not gridsData[defCnf.bossGrid].isOpen then
			local bossOpen = true
			for i=1,#defCnf.monstersGrid do
				local monsterGridData = gridsData[defCnf.monstersGrid[i]]
				if monsterGridData.gridType == YjTreasureLogic.YJ_TREASURE_GRID_MONSTER then
					bossOpen = nil
				end
			end
			if bossOpen then
				gridsData[defCnf.bossGrid].isOpen = 1
			end
		end
	end
    YjTreasureDBLogic.addItem(itemTb,human.db._id)
	roleData.killMonster = roleData.killMonster or {}
	roleData.killMonster.killCnt = (roleData.killMonster.killCnt or 0) + 1

	YjTreasureDBLogic.updateUuid2Role(roleData)

	if msgRet.list[0] > 0 then
		--Msg.trace(msgRet)
		Msg.send(msgRet,human.fd)
	end
end

-- 扫荡格子
function sdMonsterOpenGrids(human,gridIndex,itemTb)
	local defCnf = YjTreasureExcel.define[1]
	local roleData = YjTreasureDBLogic.getRoleDataByUuid(human.db._id)
	local layerData = roleData.layerData
	if not layerData then return end
	local gridsData = layerData.grids
	if not gridsData then return end
	local gridData = gridsData[gridIndex]
	if not gridData then return end

    local buff = nil
	if gridData.gridType == YjTreasureLogic.YJ_TREASURE_GRID_BOSS then
		gridsData[gridIndex] = {}
		gridsData[gridIndex].gridType = YjTreasureLogic.YJ_TREASURE_GRID_DOOR
		gridsData[gridIndex].isOpen = 1
		roleData.tansuo = (roleData.tansuo or 0) + 1
	elseif gridData.gridType == YjTreasureLogic.YJ_TREASURE_GRID_MONSTER then
		local openGrids = getOpenGrids(human.db._id,gridIndex)
		if not openGrids then return end

		gridsData[gridIndex] = {}
		gridsData[gridIndex].gridType = YjTreasureLogic.YJ_TREASURE_GRID_KONGDI
		gridsData[gridIndex].isOpen = 1

		roleData.tansuo = (roleData.tansuo or 0) + #openGrids + 1 --算上怪物格子
		for i=1,#openGrids do
			local openIndex = openGrids[i]
			local data = gridsData[openIndex]
			local change = nil

			if data.gridType == YjTreasureLogic.YJ_TREASURE_GRID_ITEM then --道具
				local item = data.item
				if item then
					local itemID = item.itemID
					local itemCnt = item.itemCnt
					layerData.getItems = layerData.getItems or {}
					layerData.getItems[itemID] = (layerData.getItems[itemID] or 0) + itemCnt
                    itemTb[itemID] = (itemTb[itemID] or 0) + itemCnt
				end
				change = true
			end

			if data.gridType == YjTreasureLogic.YJ_TREASURE_GRID_YJSHOPER then --遗迹商人
				roleData.yjShoperCnt = (roleData.yjShoperCnt or 0) + 1
				change = true
			end

			if data.gridType == YjTreasureLogic.YJ_TREASURE_GRID_TREASURE_SHOP then --商店
				YjTreasureDBLogic.makeTreasureShop(human.db._id,openIndex)
			end

			if data.gridType == YjTreasureLogic.YJ_TREASURE_GRID_BUFF then --buff
				change = true
				buff = YjTreasureDBLogic.makeBuff(human.db._id)
			end

			gridsData[openIndex].isOpen = 1

			if change then
				gridsData[openIndex] = {}
				gridsData[openIndex].gridType = YjTreasureLogic.YJ_TREASURE_GRID_KONGDI
				gridsData[openIndex].isOpen = 1
			end
		end
		--四个守卫击败，方可挑战boss
		if not gridsData[defCnf.bossGrid].isOpen then
			local bossOpen = true
			for i=1,#defCnf.monstersGrid do
				local monsterGridData = gridsData[defCnf.monstersGrid[i]]
				if monsterGridData.gridType == YjTreasureLogic.YJ_TREASURE_GRID_MONSTER then
					bossOpen = nil
				end
			end
			if bossOpen then
				gridsData[defCnf.bossGrid].isOpen = 1
			end
		end
	end

	roleData.killMonster = roleData.killMonster or {}
	roleData.killMonster.killCnt = (roleData.killMonster.killCnt or 0) + 1

	YjTreasureDBLogic.updateUuid2Role(roleData)
end

function onFightEnd(human, result, type, gridIndex, combatInfo, isQuick)
	resetCombatHp(human.db._id,combatInfo,gridIndex) --刷新血量
	if CombatDefine.RESULT_WIN == result then -- 胜利处理
		killMonsterOpenGrids(human,gridIndex)
		LiLianLogic.onCallback(human,LiLianLogic.LILIAN_OUTID13,1)
		YjTreasureDBLogic.sortYJboard()
        ChengjiuLogic.onCallback(human,ChengjiuDefine.CJ_TASK_TYPE_19,1)
		HeroGrowUp.onCallback(human, HeroGrowUp.TASKTYPE20, 1)
	end

	YjTreasureLogic.CG_YJTREASURE_QUERY(human,1)
end

--扫荡
function CG_YJTREASURE_SAODANG(human)
	local roleData = YjTreasureDBLogic.getRoleDataByUuid(human.db._id)
	if not roleData or not roleData.rolebase then return end
	local layerData = roleData.layerData
	if not layerData or not layerData.grids then return end
	local gridsData = layerData.grids

	local defCnf = YjTreasureExcel.define[1]
	local zhandouli = roleData.rolebase.zhandouli
	if zhandouli < defCnf.saodangNeed then
		local content = Util.format(Lang.YJTREASURE_SANGDAO_ZHANDOULI,defCnf.saodangNeed)
		return Broadcast.sendErr(human,content)
	end

	local saodangMax = defCnf.saodangMax
	local saodangNow = roleData.sangdang or 0
	if saodangNow >= saodangMax then
		Broadcast.sendErr(human,Lang.YJTREASURE_SANGDAO_CNT_ERR)
	end

	local left = saodangMax - saodangNow
	local monstersGridCnf = defCnf.monstersGrid
	local bossGrid = defCnf.bossGrid
	local obj, pos = YjTreasureDBLogic.getFightHeroObj(roleData.objList)
	local heroZhandouli = obj.attrs[RoleDefine.ZHANDOULI]

	local kill = nil
	local up = nil
    local itemTb = {}
	for i=1,YjTreasureLogic.YJ_TREASURE_MONSTERS do
		if (roleData.sangdang or 0) >= saodangMax then
			break
		end

		local gridIndex = monstersGridCnf[i]
		if not gridIndex then
			gridIndex = bossGrid
		end
		local gridData = gridsData[gridIndex]
		local monsterObjList = gridData.monsterObjList
        if monsterObjList then
		    local monsterZhandouli = gridData.monsterRBase.zhandouli
		    
		    for pos in pairs(monsterObjList) do
		    	if monsterObjList[pos] then
		    		if heroZhandouli > monsterZhandouli then
		    			monsterObjList[pos].hp = 0
		    			kill = true
		    		else
		    			kill = nil
		    		end
		    	end
		    end

		    if kill then
		    	sdMonsterOpenGrids(human,gridIndex,itemTb)
		    	LiLianLogic.onCallback(human,LiLianLogic.LILIAN_OUTID13,1)
                HeroGrowUp.onCallback(human, HeroGrowUp.TASKTYPE20, 1)
                ChengjiuLogic.onCallback(human,ChengjiuDefine.CJ_TASK_TYPE_19,1)
		    	roleData.sangdang = (roleData.sangdang or 0) + 1
		    	up = true
		    end
        end
	end

    BagLogic.addItemList(human, itemTb, "yj_treasure")
    YjTreasureDBLogic.addItem(itemTb,human.db._id)

	if up then
		YjTreasureDBLogic.sortYJboard()
		YjTreasureDBLogic.updateUuid2Role(roleData)
		YjTreasureLogic.CG_YJTREASURE_QUERY(human,1)
    else
        Broadcast.sendErr(human,Lang.YJTREASURE_SANGDAO_ZHANDOULI_1)
	end
end
